module rr_dispatch #(parameter WD = 2, KEEP_MODE = 1)
(
	input clk,
	input rst_n,
	input [WD -1:0] req,	
	input ack,
	
	output [WD -1:0] grant
);

wire [WD -1:0] req_real;

generate
    if(KEEP_MODE == 1)begin: KEEP_MODE_PATH
        reg keep;
        reg [WD -1:0]req_old;
        always @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                keep    <= 1'b0;
                req_old <= {WD{1'b0}};
            end
            else if(ack)begin
                keep <= 1'b0;
            end
            else if((|req) && (~keep))begin
                keep    <= 1'b1;
                req_old <= req;
            end
        end
        assign req_real = keep ? req_old : req;
    end
    else begin: NO_KEEP_MODE_PATH
        assign req_real = req;
    end
endgenerate

reg  [WD -1:0] req_power;
wire [WD -1:0] req_after_power = req_real & req_power;

wire [WD -1:0] old_mask = {req_after_power[WD -2:0] | old_mask[WD -2:0], 1'b0};
wire [WD -1:0] new_mask = {req_real[WD -2:0]        | new_mask[WD -2:0], 1'b0};

wire old_grant_work = (|req_after_power);

wire [WD -1:0] old_grant = ~old_mask & req_after_power;
wire [WD -1:0] new_grant = ~new_mask & req_real;

always @(posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		req_power <= {WD{1'b1}};
	end
	else if(ack) begin
		if(old_grant_work)begin
			req_power <= old_mask;
		end
		else if(|req)begin
			req_power <= new_mask;
		end
	end
end

assign grant = old_grant_work ? old_grant : new_grant;

endmodule
